﻿using Autofac;
using Framework.Domain.DomainObject;
using Framework.Domain.DomainObject.Bo;
using Framework.Domain.Interface.DomainObject.UnitOfWork;
using Framework.Domain.Interface.Factorys;
using Framework.Domain.Interface.Repository;
using Framework.Domain.Interface.SearchCriterias;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace Framework.Domain.Repository
{
    public abstract class BoRepository<IBaseBo, TEntity, ISearchCriterias> : IBoRepository<IBaseBo, ISearchCriterias>
         where TEntity : BaseBoEntity
    {
        private Expression<Func<TEntity, bool>> permanentCondition = (i => true);
        private IAppUnitOfWork _unitOfWork;

        public void Add(IBaseBo bo)
        {
            if (bo != null)
            {
                BaseBo baseBo = bo as BaseBo;
                BaseBoEntity itemEntity = baseBo.GetEntity();
                itemEntity.CreateTime = System.DateTime.Now;
                if (itemEntity.CreateUserKeyId == default(Guid))
                {
                    itemEntity.CreateUserKeyId = Guid.Parse("99999999-9999-9999-9999-999999999999");
                }
                itemEntity.UpdateTime = System.DateTime.Now;
                itemEntity.UpdateUserKeyId = Guid.Parse("99999999-9999-9999-9999-999999999999");
                itemEntity.Version = 1;
                itemEntity.IsDelete = false;
                this.GetSet().Add((TEntity)itemEntity);
            }
            else
            {
                throw new Exception("Domain对象转换层 ORM 对象时失败");

            }
        }

        public IBaseBo Find(Guid keyId)
        {
            TEntity entity = unitOfWork().CreateSet<TEntity>().Find(keyId);
            if (entity == null)
            {
                return default;
            }
            var bo = this.Convert(entity);
            return bo;
        }

        private IBaseBo Convert(TEntity entity)
        {
            return ExampleFactory.CreateAppService<IBaseBo>(new NamedParameter("entity", entity));
        }

        private DbSet<TEntity> GetSet()
        {
            return this.unitOfWork().CreateSet<TEntity>();
        }

        private IAppUnitOfWork unitOfWork()
        {
            if (_unitOfWork == null)
                _unitOfWork = AppUnitOfWorkFactory.GetAppUnitOfWorkRepository();
            return _unitOfWork;
        }


        protected abstract Expression<Func<TEntity, bool>> ParseSearchCriteria(ISearchCriterias searchCriteria);



        public IQueryable<IBaseBo> GetQuery(ISearchCriterias searchCriteria)
        {
            Expression<Func<TEntity, bool>> myFilter = this.permanentCondition;
            if (searchCriteria != null)
            {
                myFilter = ParseSearchCriteria(searchCriteria);
            }
            IQueryable<TEntity> entities = this.GetSet().Where(myFilter);

            string tempSQL = entities.ToString();

            IList<IBaseBo> list = Convert(entities.AsEnumerable());
            return list.AsQueryable();
        }

        public IList<IBaseBo> Convert(IEnumerable<TEntity> entities)
        {
            List<IBaseBo> list = new List<IBaseBo>();
            foreach (TEntity entity in entities)
            {
                list.Add(Convert(entity));
            }
            return list;
        }

    }
}
